﻿using System;
using Business.Entity.Contabil.Pessoa;
using Business.Entity.Contabil.Pessoa.SubClass.Empresa;
using Business.Entity.Contabil.Pessoa.SubClass.Usuario;
using Business.Entity.Estoque.Produto;
using Business.Entity.Vendas.MovimentacaoCaixa.SubClass.RecebimentoVenda;
using Business.Entity.Vendas.Pedido.ClassesRelacionadas;
using Business.Enum;
using NHibernate;

namespace Business.Entity.Vendas.Pedido.Restaurante
{
    public class PedidoRestauranteRepository : RepositoryBase<PedidoRestaurante>
    {
        public static PedidoRestaurante Save(PedidoRestaurante pedido)
        {
            ISession session = GetSession();
            ITransaction transaction = session.BeginTransaction();
            try
            {
                UsuarioRepository.Session = PedidoRepository.GetSession();
                PessoaRepository.Session = PedidoRepository.GetSession();
                EmpresaRepository.Session = PedidoRepository.GetSession();
                ProdutoRepository.Session = PedidoRepository.GetSession();
                CondicaoPagamentoRepository.Session = PedidoRepository.GetSession();
                FormaPagamentoRepository.Session = PedidoRepository.GetSession();

                pedido.CondicaoPagamento = CondicaoPagamentoRepository.GetById(
                    pedido.CondicaoPagamento.Id);
                pedido.Usuario = UsuarioRepository.GetById(Utils.UsuarioAtual.Id);
                pedido.Cliente = PessoaRepository.GetById(pedido.Cliente.Id);
                pedido.Empresa = EmpresaRepository.GetById(
                    Utils.Terminal.Empresa.Id);

                foreach (var pag in pedido.Pagamento)
                {
                    pag.FormaPagamento = FormaPagamentoRepository.GetById(
                        pag.FormaPagamento.Id);
                }
                foreach (var comp in pedido.Produtos)
                {

                    comp.Produto = ProdutoRepository.GetById(comp.Produto.Id);
                    foreach (var prod in comp.Composicao)
                    {
                        prod.Produto = ProdutoRepository.GetById(prod.Produto.Id);
                    }
                }
                session.Save(pedido);
                RepositoryBase<RecebimentoVenda>.Session = session;
                foreach (var pag in pedido.Pagamento)
                {
                    pag.Pedido = pedido;
                    // Cria o recebimento da venda para o caixa.
                    session.Save(RecebimentoVendaRepository
                        .CreateRecebimentoVendaByPedido(pag));
                }
                // Efetua o lançamento no contávil.
                EfetuarLancamentoRestaurante(session, pedido);
                // Baixa as quantidades no estoque.
                BaixaEstoque(session, pedido);
                transaction.Commit();
            }
            catch (Exception)
            {
                transaction.Rollback();
                throw;
            }

            return pedido;
        }

        public static bool EfetuarLancamentoRestaurante(ISession session, PedidoRestaurante pedido)
        {
            RepositoryBase<Pedido>.Session = session;
            foreach (var pag in pedido.Pagamento)
            {
                var fator = pag.ValorTotal / pedido.ValorPedido;
                var lanc = PedidoRepository.CriaLancamento(pedido, PedidoRepository.CriaHistorico(pedido));
                lanc.Valor = fator * pag.Valor;
                lanc.Desconto = pag.Desconto;
                lanc.Juros = pag.Juros;
                foreach (var prod in pedido.Produtos)
                {
                    PedidoRepository.DeterminarPartida(lanc, prod.Produto, pag.FormaPagamento);
                }
                if (!pag.FormaPagamento.AVista)
                {
                    PedidoRepository.LancaTitulo(pag);
                }
                //session.Save(lanc);
            }
            return true;
        }

        private static void BaixaEstoque(ISession session, PedidoRestaurante pedido)
        {
            // Entra dentro dos produtos.
            foreach (var prods in pedido.Produtos)
            {
                // Entra dentro das composições do produto.
                // Observação: Todo produto é paixado por meio de sua composição nos pedidos de restaurante,
                // sejam eles produção própria ou de terceiros.
                foreach (var composicao in prods.Composicao)
                {
                    if (composicao.Produto.Ippt == Ippt.Propria)
                    {

                        if (composicao.Produto.Receitas.Count > 0)
                        {
                            foreach (var itemReceita in composicao.Produto.Receitas)
                            {
                                var qtd = itemReceita.Quantidade * (composicao.Quantidade *
                                          composicao.Produto.UnidadeVenda.Quantidade);
                                ProdutoRepository.BaixarQuantidadeProduto(session, itemReceita.MateriaPrima, qtd);
                            }
                        }
                        else
                        {
                            var qtd = (composicao.Quantidade *
                                          composicao.Produto.UnidadeVenda.Quantidade);
                            ProdutoRepository.BaixarQuantidadeProduto(session, composicao.Produto, qtd);
                        }

                    }
                    else
                    {
                        var qtd = (composicao.Quantidade *
                                          composicao.Produto.UnidadeVenda.Quantidade);
                        ProdutoRepository.BaixarQuantidadeProduto(session, composicao.Produto, qtd);
                    }

                }
            }
        }

        public static decimal CalcularValorPedidoRestaurante(PedidoRestaurante pedido)
        {
            decimal total = 0;
            foreach (var prod in pedido.Produtos)
            {
                total += prod.Valor;
            }
            return total;
        }
    }
}
